home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / gepackte_disketten / 1994 / 08_94_5.dms / 08_94_5.adf / term-4.0-Source.lha / termConsole.c < prev    next >
C/C++ Source or Header  |  1994-07-09  |  51KB  |  3,015 lines

  1. /*
  2. **    termConsole.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11. #include "termEmulationProcess.h"
  12.  
  13.     /* Character set modes. */
  14.  
  15. enum    {    MODE_STANDARD,MODE_GFX };
  16.  
  17.     /* Hints for the data flow scanner. */
  18.  
  19. STATIC WORD        ScanStart,
  20.             ScanEnd;
  21.  
  22. STATIC WORD __far    AttentionCount[SCAN_COUNT],
  23.             AttentionLength[SCAN_COUNT],
  24.             FlowCount;
  25.  
  26.     /* Temporary console working buffer. */
  27.  
  28. STATIC UBYTE __far    ConTempBuffer[512];
  29.  
  30.     /* Text output data. */
  31.  
  32. STATIC UBYTE        CurrentFontScale,FontScalingRequired;
  33. STATIC WORD        LastPrintableColumn;
  34.  
  35.     /* ConTranslateSetup():
  36.      *
  37.      *    Set up for buffer translation.
  38.      */
  39.  
  40. STATIC VOID __inline
  41. ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  42. {
  43.     Handle -> LocalBuffer        = NULL;
  44.     Handle -> LocalLen        = 0;
  45.  
  46.     Handle -> SourceBuffer        = SourceBuffer;
  47.     Handle -> SourceLen        = SourceLen;
  48.  
  49.     Handle -> DestinationBuffer    = DestinationBuffer;
  50.     Handle -> DestinationLen    = DestinationLen;
  51.  
  52.     Handle -> Table            = Table;
  53. }
  54.  
  55.     /* ConTranslateBuffer(struct TranslationHandle *Handle):
  56.      *
  57.      *    Translate buffer contents according to
  58.      *    translation table contents.
  59.      */
  60.  
  61. STATIC LONG __inline
  62. ConTranslateBuffer(struct TranslationHandle *Handle)
  63. {
  64.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  65.     register LONG                 BytesWritten    = 0;
  66.     register struct TranslationEntry    *Entry;
  67.  
  68.         /* Are we to return any translated data? */
  69.  
  70.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  71.     {
  72.             /* Decrement number of bytes in buffer. */
  73.  
  74.         Handle -> LocalLen--;
  75.  
  76.             /* Return next character. */
  77.  
  78.         *Data++ = *Handle -> LocalBuffer++;
  79.  
  80.             /* Add another byte. */
  81.  
  82.         BytesWritten++;
  83.     }
  84.  
  85.         /* Loop until done. */
  86.  
  87.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  88.     {
  89.             /* Another byte eaten. */
  90.  
  91.         Handle -> SourceLen--;
  92.  
  93.             /* Get table entry. */
  94.  
  95.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  96.         {
  97.                 /* Copy to local data area. */
  98.  
  99.             Handle -> LocalBuffer    = Entry -> String;
  100.             Handle -> LocalLen    = Entry -> Len;
  101.  
  102.                 /* Translate the data. */
  103.  
  104.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  105.             {
  106.                     /* Decrement number of bytes in buffer. */
  107.  
  108.                 Handle -> LocalLen--;
  109.  
  110.                     /* Return next character. */
  111.  
  112.                 *Data++ = *Handle -> LocalBuffer++;
  113.  
  114.                     /* Add another byte. */
  115.  
  116.                 BytesWritten++;
  117.             }
  118.         }
  119.     }
  120.  
  121.     return(BytesWritten);
  122. }
  123.  
  124.     /* TrapFilter(register STRPTR Data,register LONG Size):
  125.      *
  126.      *    Handle the trap list, similar to FlowFilter().
  127.      */
  128.  
  129. STATIC VOID __regargs
  130. TrapFilter(register STRPTR Data,register LONG Size)
  131. {
  132.     STATIC LONG WaitCount = 0;
  133.  
  134.     struct List    *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
  135.     struct TrapNode    *Node;
  136.  
  137.     register UBYTE c,Mask;
  138.  
  139.     ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  140.  
  141.     if(Config -> SerialConfig -> StripBit8)
  142.         Mask = 0x7F;
  143.     else
  144.         Mask = 0xFF;
  145.  
  146.     do
  147.     {
  148.         register BOOLEAN MatchMade;
  149.  
  150.         c = (*Data++) & Mask;
  151.  
  152.         do
  153.         {
  154.             MatchMade = FALSE;
  155.  
  156.             for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  157.             {
  158.                 if(Node -> Count == WaitCount)
  159.                 {
  160.                     if(c == (Node -> Sequence[WaitCount] & Mask))
  161.                     {
  162.                         MatchMade = TRUE;
  163.  
  164.                         if(++Node -> Count == Node -> SequenceLen)
  165.                         {
  166.                             struct DataMsg *Msg;
  167.  
  168.                             Node -> Count = 0;
  169.  
  170.                             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
  171.                             {
  172.                                 Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
  173.                                 Msg -> Data = (STRPTR)(Msg + 1);
  174.  
  175.                                 strcpy(Msg -> Data,Node -> Command);
  176.  
  177.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  178.                             }
  179.                         }
  180.                     }
  181.                 }
  182.             }
  183.  
  184.             if(MatchMade)
  185.                 WaitCount++;
  186.             else
  187.             {
  188.                 if(WaitCount)
  189.                 {
  190.                     WaitCount = 0;
  191.  
  192.                     for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  193.                         Node -> Count = 0;
  194.                 }
  195.                 else
  196.                     break;
  197.             }
  198.         }
  199.         while(!WaitCount);
  200.     }
  201.     while(--Size);
  202.  
  203.     ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  204. }
  205.  
  206.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  207.      *
  208.      *    Data flow filter.
  209.      */
  210.  
  211. STATIC VOID __regargs
  212. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  213. {
  214.     register UBYTE c;
  215.  
  216.         /* Run until done. */
  217.  
  218.     do
  219.     {
  220.         if(c = (*Data++ & Mask))
  221.         {
  222.  
  223.                 /* We already got a `CONNECT',
  224.                  * Continue scanning the serial output
  225.                  * data for the actual baud rate.
  226.                  */
  227.  
  228.             if(BaudPending)
  229.             {
  230.                 if(c < ' ')
  231.                 {
  232.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  233.                         BaudCount--;
  234.  
  235.                     BaudBuffer[BaudCount] = 0;
  236.  
  237.                     FlowInfo . Connect = TRUE;
  238.                     FlowInfo . Changed = TRUE;
  239.  
  240.                     BaudPending = FALSE;
  241.  
  242.                     DTERate = GetBaudRate(BaudBuffer);
  243.  
  244.                     if(Quiet && Size > 1)
  245.                     {
  246.                         DataHold = Data;
  247.                         DataSize = Size - 1;
  248.                     }
  249.                 }
  250.                 else
  251.                 {
  252.                     if(BaudCount || c != ' ')
  253.                     {
  254.                         BaudBuffer[BaudCount++] = c;
  255.  
  256.                         if(BaudCount == 79)
  257.                         {
  258.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  259.                                 BaudCount--;
  260.  
  261.                             BaudBuffer[BaudCount] = 0;
  262.  
  263.                             FlowInfo . Connect = TRUE;
  264.                             FlowInfo . Changed = TRUE;
  265.  
  266.                             BaudPending = FALSE;
  267.  
  268.                             DTERate = GetBaudRate(BaudBuffer);
  269.  
  270.                             if(Quiet && Size > 1)
  271.                             {
  272.                                 DataHold = Data;
  273.                                 DataSize = Size - 1;
  274.                             }
  275.                         }
  276.                     }
  277.                 }
  278.             }
  279.             else
  280.             {
  281.                 register BYTE MatchMade;
  282.                 register WORD i;
  283.  
  284.                 do
  285.                 {
  286.                     MatchMade = FALSE;
  287.  
  288.                         /* Scan all ID strings for matches. */
  289.  
  290.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  291.                     {
  292.                             /* This sequence is a likely
  293.                              * match.
  294.                              */
  295.  
  296.                         if(AttentionCount[i] == FlowCount)
  297.                         {
  298.                                 /* Does the character
  299.                                  * fit into the sequence?
  300.                                  */
  301.  
  302.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  303.                             {
  304.                                 MatchMade = TRUE;
  305.  
  306.                                     /* Did we hit the
  307.                                      * last character
  308.                                      * in the sequence?
  309.                                      */
  310.  
  311.                                 if(++AttentionCount[i] == AttentionLength[i])
  312.                                 {
  313.                                         /* We've got a valid
  314.                                          * sequence, now look
  315.                                          * which flags to change.
  316.                                          */
  317.  
  318.                                     switch(i)
  319.                                     {
  320.                                             /* We got a `no carrier' message. */
  321.  
  322.                                         case SCAN_NOCARRIER:
  323.  
  324.                                             if(Config -> SerialConfig -> CheckCarrier)
  325.                                             {
  326.                                                 WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  327.  
  328.                                                 DoIO(WriteRequest);
  329.  
  330.                                                     /* Is the carrier still present? */
  331.  
  332.                                                 if(!(WriteRequest -> io_Status & CIAF_COMCD))
  333.                                                     break;
  334.                                             }
  335.  
  336.                                             if(!FlowInfo . NoCarrier)
  337.                                             {
  338.                                                 FlowInfo . NoCarrier    = TRUE;
  339.                                                 FlowInfo . Changed    = TRUE;
  340.                                             }
  341.  
  342.                                             WasOnline = Online;
  343.  
  344.                                             Online = FALSE;
  345.  
  346.                                                 /* Clear the password. */
  347.  
  348.                                             Password[0] = 0;
  349.                                             UserName[0] = 0;
  350.  
  351.                                             CurrentBBSName[0]    = 0;
  352.                                             CurrentBBSComment[0]    = 0;
  353.                                             CurrentBBSNumber[0]    = 0;
  354.  
  355.                                             if(WasOnline)
  356.                                             {
  357.                                                 StopCall(FALSE);
  358.  
  359.                                                 Say(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
  360.  
  361.                                                 SetDialMenu(TRUE);
  362.                                             }
  363.  
  364.                                             break;
  365.  
  366.                                             /* Got another call. */
  367.  
  368.                                         case SCAN_RING:
  369.  
  370.                                             if(!FlowInfo . Ring)
  371.                                             {
  372.                                                 FlowInfo . Ring        = TRUE;
  373.                                                 FlowInfo . Changed    = TRUE;
  374.                                             }
  375.  
  376.                                             break;
  377.  
  378.                                             /* Got a voice call. */
  379.  
  380.                                         case SCAN_VOICE:
  381.  
  382.                                             if(!FlowInfo . Voice)
  383.                                             {
  384.                                                 FlowInfo . Voice    = TRUE;
  385.                                                 FlowInfo . Changed    = TRUE;
  386.                                             }
  387.  
  388.                                             break;
  389.  
  390.                                             /* Got a connect message. */
  391.  
  392.                                         case SCAN_CONNECT:
  393.  
  394.                                                 /* Are we to check the carrier signal? */
  395.  
  396.                                             if(Config -> SerialConfig -> CheckCarrier)
  397.                                             {
  398.                                                 WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  399.  
  400.                                                 DoIO(WriteRequest);
  401.  
  402.                                                     /* Is the carrier signal present, i.e.
  403.                                                      * was the `CONNECT' message valid?
  404.                                                      */
  405.  
  406.                                                 if(WriteRequest -> io_Status & CIAF_COMCD)
  407.                                                     break;
  408.                                             }
  409.  
  410.                                             WasOnline = Online;
  411.  
  412.                                             if(!Online)
  413.                                             {
  414.                                                 BaudBuffer[0]    = 0;
  415.  
  416.                                                 BaudPending    = TRUE;
  417.                                                 BaudCount    = 0;
  418.                                             }
  419.  
  420.                                             break;
  421.  
  422.                                             /* Got the ZModem inquiry sequence. */
  423.  
  424.                                         case SCAN_ZMODEM:
  425.  
  426.                                             if(!FlowInfo . ZModemUpload)
  427.                                             {
  428.                                                 FlowInfo . ZModemUpload    = TRUE;
  429.                                                 FlowInfo . Changed    = TRUE;
  430.                                             }
  431.  
  432.                                             break;
  433.  
  434.                                             /* Line is busy. */
  435.  
  436.                                         case SCAN_BUSY:
  437.  
  438.                                             if(!FlowInfo . Busy)
  439.                                             {
  440.                                                 FlowInfo . Busy        = TRUE;
  441.                                                 FlowInfo . Changed    = TRUE;
  442.                                             }
  443.  
  444.                                             break;
  445.  
  446.                                         case SCAN_NODIALTONE:
  447.  
  448.                                             if(!FlowInfo . NoDialTone)
  449.                                             {
  450.                                                 FlowInfo . NoDialTone    = TRUE;
  451.                                                 FlowInfo . Changed    = TRUE;
  452.                                             }
  453.  
  454.                                             break;
  455.                                     }
  456.                                 }
  457.                             }
  458.                         }
  459.                     }
  460.  
  461.                     if(MatchMade)
  462.                         FlowCount++;
  463.                     else
  464.                     {
  465.                         if(FlowCount)
  466.                         {
  467.                             FlowCount = 0;
  468.  
  469.                             memset(AttentionCount,0,sizeof(AttentionCount));
  470.                         }
  471.                         else
  472.                             break;
  473.                     }
  474.                 }
  475.                 while(!FlowCount);
  476.             }
  477.         }
  478.     }
  479.     while(--Size);
  480. }
  481.  
  482.     /* StripSequence():
  483.      *
  484.      *    Strips a string from ESC and CSI introduced control
  485.      *    sequences.
  486.      */
  487.  
  488. STATIC LONG __regargs
  489. StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
  490. {
  491.     STATIC BYTE    HasESC    = FALSE,
  492.             HasCSI    = FALSE;
  493.     LONG        Size    = 0;
  494.  
  495.     while(Length--)
  496.     {
  497.         if(HasESC)
  498.         {
  499.             if(*Src == '[')
  500.             {
  501.                 HasESC = FALSE;
  502.                 HasCSI = TRUE;
  503.             }
  504.             else
  505.             {
  506.                 if(*Src >= '0')
  507.                     HasESC = FALSE;
  508.             }
  509.  
  510.             Src++;
  511.  
  512.             continue;
  513.         }
  514.  
  515.         if(HasCSI)
  516.         {
  517.             if(*Src >= '@')
  518.                 HasCSI = FALSE;
  519.  
  520.             Src++;
  521.  
  522.             continue;
  523.         }
  524.  
  525.         switch(*Src)
  526.         {
  527.             case CAN:
  528.             case SUB:
  529.  
  530.                 HasESC = HasCSI = FALSE;
  531.                 break;
  532.  
  533.             case '\r':
  534.  
  535.                 break;
  536.  
  537.             case ESC:
  538.  
  539.                 HasESC = TRUE;
  540.                 break;
  541.  
  542.             case CSI:
  543.  
  544.                 HasCSI = TRUE;
  545.                 break;
  546.  
  547.             default:
  548.  
  549.                 if(IsPrintable[*Src])
  550.                 {
  551.                     *Dst++ = *Src;
  552.  
  553.                     Size++;
  554.                 }
  555.  
  556.                 break;
  557.         }
  558.  
  559.         Src++;
  560.     }
  561.  
  562.     return(Size);
  563. }
  564.  
  565.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  566.      *
  567.      *    Raw text output routine, printer capture flavour.
  568.      */
  569.  
  570. STATIC VOID
  571. ConOutputPrinter(STRPTR Buffer,LONG Size)
  572. {
  573.     if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
  574.     {
  575.         BlockWindows();
  576.  
  577.         if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  578.             ClosePrinterCapture(TRUE);
  579.  
  580.         ReleaseWindows();
  581.     }
  582. }
  583.  
  584.     /* ConOutputCaptureGFX(STRPTR Buffer,LONG Size):
  585.      *
  586.      *    Raw text output routine, GFX text & capture flavour.
  587.      */
  588.  
  589. STATIC VOID 
  590. ConOutputCaptureGFX(STRPTR Buffer,LONG Size)
  591. {
  592.     register WORD Offset;
  593.  
  594.         /* Do we still have a character in the
  595.          * magnificient buffer?
  596.          */
  597.  
  598.     while(Size)
  599.     {
  600.             /* Cursor is positioned at
  601.              * the right hand side of the
  602.              * display. If auto-wrap is
  603.              * enabled, perform some
  604.              * kind of CR/LF, else leave
  605.              * the cursor where it is and
  606.              * quit the show.
  607.              */
  608.  
  609.         if(CursorX > LastPrintableColumn)
  610.         {
  611.                 /* Wrap cursor. */
  612.  
  613.             if(Config -> EmulationConfig -> LineWrap)
  614.             {
  615.                     /* Move to beginning of next line. */
  616.  
  617.                 CursorX = 0;
  618.  
  619.                 DownLine();
  620.  
  621.                 Capture("\n",1);
  622.  
  623.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  624.  
  625.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  626.  
  627.                 LastPrintableColumn = LastColumn;
  628.  
  629.                     /* Reposition cursor, don't redraw it. */
  630.  
  631.                 ClipBlitCursor(FALSE,TRUE);
  632.             }
  633.             else
  634.             {
  635.                     /* Stop the cursor. */
  636.  
  637.                 CursorX = LastPrintableColumn;
  638.  
  639.                 Capture(Buffer,Size);
  640.  
  641.                     /* Make it reappear. */
  642.  
  643.                 ClipBlitCursor(FALSE,TRUE);
  644.  
  645.                 return;
  646.             }
  647.         }
  648.  
  649.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  650.             Offset = Size;
  651.  
  652.         if(Config -> EmulationConfig -> InsertMode)
  653.         {
  654.             RasterShiftChar(Offset);
  655.  
  656.             ScrollLineShiftChar(Offset);
  657.  
  658.             ShiftChar(Offset);
  659.         }
  660.  
  661.         RasterPutString(Buffer,Offset);
  662.  
  663.         ScrollLinePutString(Offset);
  664.  
  665.         if(FontScalingRequired)
  666.             PrintScaled(Buffer,Offset,CurrentFontScale);
  667.         else
  668.             GfxText(RPort,Buffer,Offset);
  669.  
  670.         Capture(Buffer,Offset);
  671.  
  672.         Buffer    += Offset;
  673.  
  674.         Size    -= Offset;
  675.  
  676.         CursorX    += Offset;
  677.     }
  678.  
  679.     ClipBlitCursor(FALSE,TRUE);
  680. }
  681.  
  682.     /* ConOutputCaptureNormal(STRPTR Buffer,LONG Size):
  683.      *
  684.      *    Raw text output routine, normal text & capture flavour.
  685.      */
  686.  
  687. STATIC VOID 
  688. ConOutputCaptureNormal(STRPTR Buffer,LONG Size)
  689. {
  690.     register WORD Offset;
  691.  
  692.     while(Size)
  693.     {
  694.         if(CursorX > LastPrintableColumn)
  695.         {
  696.             if(Config -> EmulationConfig -> LineWrap)
  697.             {
  698.                 CursorX = 0;
  699.  
  700.                 DownLine();
  701.  
  702.                 Capture("\n",1);
  703.  
  704.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  705.  
  706.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  707.  
  708.                 LastPrintableColumn = LastColumn;
  709.  
  710.                 ClipBlitCursor(FALSE,TRUE);
  711.             }
  712.             else
  713.             {
  714.                 CursorX = LastPrintableColumn;
  715.  
  716.                 Capture(Buffer,Size);
  717.  
  718.                 ClipBlitCursor(FALSE,TRUE);
  719.  
  720.                 return;
  721.             }
  722.         }
  723.  
  724.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  725.             Offset = Size;
  726.  
  727.         if(Config -> EmulationConfig -> InsertMode)
  728.         {
  729.             RasterShiftChar(Offset);
  730.  
  731.             ScrollLineShiftChar(Offset);
  732.  
  733.             ShiftChar(Offset);
  734.         }
  735.  
  736.         RasterPutString(Buffer,Offset);
  737.  
  738.         ScrollLinePutString(Offset);
  739.  
  740.         if(FontScalingRequired)
  741.             PrintScaled(Buffer,Offset,CurrentFontScale);
  742.         else
  743.             Text(RPort,Buffer,Offset);
  744.  
  745.         Capture(Buffer,Offset);
  746.  
  747.         Buffer    += Offset;
  748.  
  749.         Size    -= Offset;
  750.  
  751.         CursorX    += Offset;
  752.     }
  753.  
  754.     ClipBlitCursor(FALSE,TRUE);
  755. }
  756.  
  757.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  758.      *
  759.      *    Raw text output routine, GFX text flavour.
  760.      */
  761.  
  762. STATIC VOID 
  763. ConOutputGFX(STRPTR Buffer,LONG Size)
  764. {
  765.     register WORD Offset;
  766.  
  767.         /* Do we still have a character in the
  768.          * magnificient buffer?
  769.          */
  770.  
  771.     while(Size)
  772.     {
  773.             /* Cursor is positioned at
  774.              * the right hand side of the
  775.              * display. If auto-wrap is
  776.              * enabled, perform some
  777.              * kind of CR/LF, else leave
  778.              * the cursor where it is and
  779.              * quit the show.
  780.              */
  781.  
  782.         if(CursorX > LastPrintableColumn)
  783.         {
  784.                 /* Wrap cursor. */
  785.  
  786.             if(Config -> EmulationConfig -> LineWrap)
  787.             {
  788.                     /* Move to beginning of next line. */
  789.  
  790.                 CursorX = 0;
  791.  
  792.                 DownLine();
  793.  
  794.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  795.  
  796.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  797.  
  798.                 LastPrintableColumn = LastColumn;
  799.  
  800.                     /* Reposition cursor, don't redraw it. */
  801.  
  802.                 ClipBlitCursor(FALSE,TRUE);
  803.             }
  804.             else
  805.             {
  806.                     /* Stop the cursor. */
  807.  
  808.                 CursorX = LastPrintableColumn;
  809.  
  810.                     /* Make it reappear. */
  811.  
  812.                 ClipBlitCursor(FALSE,TRUE);
  813.  
  814.                 return;
  815.             }
  816.         }
  817.  
  818.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  819.             Offset = Size;
  820.  
  821.         if(Config -> EmulationConfig -> InsertMode)
  822.         {
  823.             RasterShiftChar(Offset);
  824.  
  825.             ScrollLineShiftChar(Offset);
  826.  
  827.             ShiftChar(Offset);
  828.         }
  829.  
  830.         RasterPutString(Buffer,Offset);
  831.  
  832.         ScrollLinePutString(Offset);
  833.  
  834.         if(FontScalingRequired)
  835.             PrintScaled(Buffer,Offset,CurrentFontScale);
  836.         else
  837.             GfxText(RPort,Buffer,Offset);
  838.  
  839.         Buffer    += Offset;
  840.  
  841.         Size    -= Offset;
  842.  
  843.         CursorX    += Offset;
  844.     }
  845.  
  846.     ClipBlitCursor(FALSE,TRUE);
  847. }
  848.  
  849.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  850.      *
  851.      *    Raw text output routine, normal text flavour.
  852.      */
  853.  
  854. STATIC VOID 
  855. ConOutputNormal(STRPTR Buffer,LONG Size)
  856. {
  857.     register WORD Offset;
  858.  
  859.     while(Size)
  860.     {
  861.         if(CursorX > LastPrintableColumn)
  862.         {
  863.             if(Config -> EmulationConfig -> LineWrap)
  864.             {
  865.                 CursorX = 0;
  866.  
  867.                 DownLine();
  868.  
  869.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  870.  
  871.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  872.  
  873.                 LastPrintableColumn = LastColumn;
  874.  
  875.                 ClipBlitCursor(FALSE,TRUE);
  876.             }
  877.             else
  878.             {
  879.                 CursorX = LastPrintableColumn;
  880.  
  881.                 ClipBlitCursor(FALSE,TRUE);
  882.  
  883.                 return;
  884.             }
  885.         }
  886.  
  887.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  888.             Offset = Size;
  889.  
  890.         if(Config -> EmulationConfig -> InsertMode)
  891.         {
  892.             RasterShiftChar(Offset);
  893.  
  894.             ScrollLineShiftChar(Offset);
  895.  
  896.             ShiftChar(Offset);
  897.         }
  898.  
  899.         RasterPutString(Buffer,Offset);
  900.  
  901.         ScrollLinePutString(Offset);
  902.  
  903.         if(FontScalingRequired)
  904.             PrintScaled(Buffer,Offset,CurrentFontScale);
  905.         else
  906.             Text(RPort,Buffer,Offset);
  907.  
  908.         Buffer    += Offset;
  909.  
  910.         Size    -= Offset;
  911.  
  912.         CursorX    += Offset;
  913.     }
  914.  
  915.     ClipBlitCursor(FALSE,TRUE);
  916. }
  917.  
  918.     /* ConProcessUpdate():
  919.      *
  920.      *    Choose the right console data processing routine.
  921.      */
  922.  
  923. VOID
  924. ConProcessUpdate(VOID)
  925. {
  926.     Forbid();
  927.  
  928.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  929.     {
  930.         if(ReceiveTable)
  931.             ConProcessData = ConProcessDataTransExternal;
  932.         else
  933.             ConProcessData = ConProcessDataExternal;
  934.     }
  935.     else
  936.     {
  937.         if(Config -> SerialConfig -> StripBit8)
  938.         {
  939.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  940.                 ConProcessData = ConProcessDataHex7;
  941.             else
  942.                 ConProcessData = ConProcessData7;
  943.         }
  944.         else
  945.         {
  946.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  947.                 ConProcessData = ConProcessDataHex8;
  948.             else
  949.                 ConProcessData = ConProcessData8;
  950.         }
  951.     }
  952.  
  953.     Permit();
  954. }
  955.  
  956.     /* ConOutputUpdate():
  957.      *
  958.      *    Choose the right raw text output routine for the job.
  959.      */
  960.  
  961. VOID
  962. ConOutputUpdate()
  963. {
  964.     Forbid();
  965.  
  966.     if(ControllerActive)
  967.         ConOutput = ConOutputPrinter;
  968.     else
  969.     {
  970.         if((Config -> CaptureConfig -> CaptureFilterMode && FileCapture) || PrinterCapture)
  971.         {
  972.             if(CurrentFont == GFX)
  973.                 ConOutput = ConOutputCaptureGFX;
  974.             else
  975.                 ConOutput = ConOutputCaptureNormal;
  976.         }
  977.         else
  978.         {
  979.             if(BufferFrozen)
  980.             {
  981.                 if(CurrentFont == GFX)
  982.                     ConOutput = ConOutputGFX;
  983.                 else
  984.                     ConOutput = ConOutputNormal;
  985.             }
  986.             else
  987.             {
  988.                 if(CurrentFont == GFX)
  989.                     ConOutput = ConOutputCaptureGFX;
  990.                 else
  991.                     ConOutput = ConOutputCaptureNormal;
  992.             }
  993.         }
  994.     }
  995.  
  996.     if(ReceiveTable)
  997.         ConDump = ConTransWrite;
  998.     else
  999.         ConDump = ConOutput;
  1000.  
  1001.     Permit();
  1002. }
  1003.  
  1004.     /* ConFontScaleUpdate():
  1005.      *
  1006.      *    Choose the right font scale for the job.
  1007.      */
  1008.  
  1009. VOID
  1010. ConFontScaleUpdate()
  1011. {
  1012.     CurrentFontScale = RasterAttr[CursorY];
  1013.  
  1014.     if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  1015.     {
  1016.         FontScalingRequired    = (CurrentFontScale != SCALE_ATTR_2X);
  1017.         LastPrintableColumn    = LastColumn;
  1018.     }
  1019.     else
  1020.     {
  1021.         if(FontScalingRequired = (CurrentFontScale != SCALE_ATTR_NORMAL))
  1022.             LastPrintableColumn = ((LastColumn + 1) / 2) - 1;
  1023.         else
  1024.             LastPrintableColumn = LastColumn;
  1025.     }
  1026. }
  1027.  
  1028.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  1029.      *
  1030.      *    Frontend for ConWrite(), including character translation.
  1031.      */
  1032.  
  1033. VOID
  1034. ConTransWrite(STRPTR Buffer,LONG Size)
  1035. {
  1036.     struct TranslationHandle    Handle;
  1037.     UBYTE                LocalBuffer[256];
  1038.  
  1039.         /* Set up for translation. */
  1040.  
  1041.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  1042.  
  1043.         /* Process and output the data. */
  1044.  
  1045.     while(Size = ConTranslateBuffer(&Handle))
  1046.         (* ConOutput)(LocalBuffer,Size);
  1047. }
  1048.  
  1049.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  1050.      *
  1051.      *    Process data, external emulation including translation flavour.
  1052.      */
  1053.  
  1054. VOID
  1055. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  1056. {
  1057.     struct TranslationHandle Handle;
  1058.  
  1059.         /* Set up for translation. */
  1060.  
  1061.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  1062.  
  1063.     if(StripBuffer)
  1064.     {
  1065.         register LONG Len;
  1066.  
  1067.             /* Process and output the data. */
  1068.  
  1069.         while(Size = ConTranslateBuffer(&Handle))
  1070.         {
  1071.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  1072.  
  1073.             XEM_HostData . Source        = ConTempBuffer;
  1074.             XEM_HostData . Destination    = StripBuffer;
  1075.  
  1076.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  1077.                 Capture(StripBuffer,Len);
  1078.         }
  1079.     }
  1080.     else
  1081.     {
  1082.             /* Process and output the data. */
  1083.  
  1084.         while(Size = ConTranslateBuffer(&Handle))
  1085.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  1086.     }
  1087. }
  1088.  
  1089.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  1090.      *
  1091.      *    Process data, external emulation flavour.
  1092.      */
  1093.  
  1094. VOID 
  1095. ConProcessDataExternal(register STRPTR String,register LONG Size)
  1096. {
  1097.     XEmulatorWrite(XEM_IO,String,Size);
  1098.  
  1099.         /* Build another string to contain
  1100.          * the pure ASCII contents, i.e.
  1101.          * not including any ESC control
  1102.          * sequences.
  1103.          */
  1104.  
  1105.     if(StripBuffer)
  1106.     {
  1107.         register LONG Len;
  1108.  
  1109.         XEM_HostData . Source        = String;
  1110.         XEM_HostData . Destination    = StripBuffer;
  1111.  
  1112.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  1113.             Capture(StripBuffer,Len);
  1114.     }
  1115. }
  1116.  
  1117.     /* ConProcessData7(register STRPTR String,register LONG Size):
  1118.      *
  1119.      *    Process data, 7 bit flavour.
  1120.      */
  1121.  
  1122. VOID 
  1123. ConProcessData7(register STRPTR String,register LONG Size)
  1124. {
  1125.     register LONG    Len = 0;
  1126.     register UBYTE    c;
  1127.  
  1128.         // Check for prescroll
  1129.  
  1130.     if(CursorY == LastLine && LastLine > 0)
  1131.     {
  1132.         LONG Scroll = 0;
  1133.  
  1134.         if(Config -> EmulationConfig -> MaxScroll)
  1135.         {
  1136.             register WORD Count = MIN(Config -> EmulationConfig -> MaxScroll,Size);
  1137.  
  1138.             if(Count > 1)
  1139.             {
  1140.                 register UBYTE    *Buffer = String;
  1141.                 register LONG     Total    = 0;
  1142.  
  1143.                 while(Count--)
  1144.                 {
  1145.                     if((*Buffer++ & 0x7F) == '\n')
  1146.                         Total++;
  1147.                 }
  1148.  
  1149.                 if(Config -> EmulationConfig -> MaxJump > Total)
  1150.                     Scroll = Config -> EmulationConfig -> MaxJump;
  1151.                 else
  1152.                     Scroll = Total;
  1153.             }
  1154.         }
  1155.         else
  1156.         {
  1157.             if(Config -> EmulationConfig -> MaxJump)
  1158.             {
  1159.                 WORD Count = MIN(Config -> EmulationConfig -> MaxJump,Size);
  1160.  
  1161.                 if(Count > 1)
  1162.                 {
  1163.                     register UBYTE    *Buffer = String;
  1164.                     register LONG     Look    = LastColumn + 1;
  1165.  
  1166.                     while(Look--)
  1167.                     {
  1168.                         if((*Buffer++ & 0x7F) == '\n')
  1169.                         {
  1170.                             if(Count > Scroll)
  1171.                                 Scroll = Count;
  1172.  
  1173.                             break;
  1174.                         }
  1175.                     }
  1176.                 }
  1177.             }
  1178.         }
  1179.  
  1180.         if(Scroll > 1)
  1181.         {
  1182.             if(Scroll > LastLine - 1)
  1183.                 Scroll = LastLine - 1;
  1184.  
  1185.             ScrollRegion(Scroll);
  1186.  
  1187.             CursorY -= Scroll;
  1188.  
  1189.             ClipBlitCursor(FALSE,TRUE);
  1190.         }
  1191.     }
  1192.  
  1193.         /* If still parsing a sequence,
  1194.          * continue with it.
  1195.          */
  1196.  
  1197.     if(InSequence)
  1198.     {
  1199.         while(Size--)
  1200.         {
  1201.             c = *String++ & 0x7F;
  1202.  
  1203.             if(!(*AbortTable[c])(c))
  1204.             {
  1205.                 InSequence = FALSE;
  1206.  
  1207.                 break;
  1208.             }
  1209.         }
  1210.     }
  1211.  
  1212.         /* Check which font we are in, if other than Topaz
  1213.          * the only invalid char is a Null (0) which will
  1214.          * display as a space if let to continue.
  1215.          */
  1216.  
  1217.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1218.     {
  1219.         while(Size-- > 0)
  1220.         {
  1221.             if(IsPrintable[c = *String++ & 0x7F])
  1222.             {
  1223.                     /* This character is associated with a
  1224.                      * special function (bell, xon, xoff, etc.).
  1225.                      */
  1226.  
  1227.                 if(SpecialTable[c])
  1228.                 {
  1229.                     if(Len)
  1230.                     {
  1231.                         (*ConDump)(ConTempBuffer,Len);
  1232.  
  1233.                         Len = 0;
  1234.                     }
  1235.  
  1236.                         /* Does this character start
  1237.                          * a control sequence?
  1238.                          */
  1239.  
  1240.                     if(InSequence = (*SpecialTable[c])(c))
  1241.                     {
  1242.                         while(Size-- > 0)
  1243.                         {
  1244.                             c = *String++ & 0x7F;
  1245.  
  1246.                             if(!(*AbortTable[c])(c))
  1247.                             {
  1248.                                 InSequence = FALSE;
  1249.  
  1250.                                 break;
  1251.                             }
  1252.                         }
  1253.                     }
  1254.                 }
  1255.                 else
  1256.                 {
  1257.                         /* Put the character into the buffer
  1258.                          * and flush it if necessary.
  1259.                          */
  1260.  
  1261.                     ConTempBuffer[Len] = c;
  1262.  
  1263.                     if(Len++ == 512)
  1264.                     {
  1265.                         (*ConDump)(ConTempBuffer,Len);
  1266.  
  1267.                         Len = 0;
  1268.                     }
  1269.                 }
  1270.             }
  1271.         }
  1272.     }
  1273.     else
  1274.     {
  1275.         while(Size-- > 0)
  1276.         {
  1277.             if(c = (*String++ & 0x7F))
  1278.             {
  1279.                     /* This character is associated with a
  1280.                      * special function (bell, xon, xoff, etc.).
  1281.                      */
  1282.  
  1283.                 if(SpecialTable[c])
  1284.                 {
  1285.                     if(Len)
  1286.                     {
  1287.                         (*ConDump)(ConTempBuffer,Len);
  1288.  
  1289.                         Len = 0;
  1290.                     }
  1291.  
  1292.                     if(InSequence = (*SpecialTable[c])(c))
  1293.                     {
  1294.                         while(Size-- > 0)
  1295.                         {
  1296.                             c = *String++ & 0x7F;
  1297.  
  1298.                             if(!(*AbortTable[c])(c))
  1299.                             {
  1300.                                 InSequence = FALSE;
  1301.  
  1302.                                 break;
  1303.                             }
  1304.                         }
  1305.                     }
  1306.                 }
  1307.                 else
  1308.                 {
  1309.                         /* Put the character into the buffer
  1310.                          * and flush it if necessary.
  1311.                          */
  1312.  
  1313.                     ConTempBuffer[Len] = c;
  1314.  
  1315.                     if(Len++ == 512)
  1316.                     {
  1317.                         (*ConDump)(ConTempBuffer,Len);
  1318.  
  1319.                         Len = 0;
  1320.                     }
  1321.                 }
  1322.             }
  1323.         }
  1324.     }
  1325.  
  1326.     if(Len)
  1327.         (*ConDump)(ConTempBuffer,Len);
  1328. }
  1329.  
  1330.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1331.      *
  1332.      *    Process data, 8 bit flavour.
  1333.      */
  1334.  
  1335. VOID 
  1336. ConProcessData8(register STRPTR String,register LONG Size)
  1337. {
  1338.     register LONG    Len = 0;
  1339.     register UBYTE    c;
  1340.  
  1341.         // Check for prescroll
  1342.  
  1343.     if(CursorY == LastLine && LastLine > 0)
  1344.     {
  1345.         LONG Scroll = 0;
  1346.  
  1347.         if(Config -> EmulationConfig -> MaxScroll)
  1348.         {
  1349.             register WORD Count = MIN(Config -> EmulationConfig -> MaxScroll,Size);
  1350.  
  1351.             if(Count > 1)
  1352.             {
  1353.                 register UBYTE    *Buffer = String;
  1354.                 register LONG     Total    = 0;
  1355.  
  1356.                 while(Count--)
  1357.                 {
  1358.                     if(*Buffer++ == '\n')
  1359.                         Total++;
  1360.                 }
  1361.  
  1362.                 if(Config -> EmulationConfig -> MaxJump > Total)
  1363.                     Scroll = Config -> EmulationConfig -> MaxJump;
  1364.                 else
  1365.                     Scroll = Total;
  1366.             }
  1367.         }
  1368.         else
  1369.         {
  1370.             if(Config -> EmulationConfig -> MaxJump)
  1371.             {
  1372.                 WORD Count = MIN(Config -> EmulationConfig -> MaxJump,Size);
  1373.  
  1374.                 if(Count > 1)
  1375.                 {
  1376.                     register UBYTE    *Buffer = String;
  1377.                     register LONG     Look    = LastColumn + 1;
  1378.  
  1379.                     while(Look--)
  1380.                     {
  1381.                         if(*Buffer++ == '\n')
  1382.                         {
  1383.                             if(Count > Scroll)
  1384.                                 Scroll = Count;
  1385.  
  1386.                             break;
  1387.                         }
  1388.                     }
  1389.                 }
  1390.             }
  1391.         }
  1392.  
  1393.         if(Scroll > 1)
  1394.         {
  1395.             if(Scroll > LastLine - 1)
  1396.                 Scroll = LastLine - 1;
  1397.  
  1398.             ScrollRegion(Scroll);
  1399.  
  1400.             CursorY -= Scroll;
  1401.  
  1402.             ClipBlitCursor(FALSE,TRUE);
  1403.         }
  1404.     }
  1405.  
  1406.     if(InSequence)
  1407.     {
  1408.         while(Size--)
  1409.         {
  1410.             c = *String++;
  1411.  
  1412.             if(!(*AbortTable[c])(c))
  1413.             {
  1414.                 InSequence = FALSE;
  1415.  
  1416.                 break;
  1417.             }
  1418.         }
  1419.     }
  1420.  
  1421.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1422.     {
  1423.         while(Size-- > 0)
  1424.         {
  1425.             if(IsPrintable[c = *String++])
  1426.             {
  1427.                 if(SpecialTable[c])
  1428.                 {
  1429.                     if(Len)
  1430.                     {
  1431.                         (*ConDump)(ConTempBuffer,Len);
  1432.  
  1433.                         Len = 0;
  1434.                     }
  1435.  
  1436.                     if(InSequence = (*SpecialTable[c])(c))
  1437.                     {
  1438.                         while(Size-- > 0)
  1439.                         {
  1440.                             c = *String++;
  1441.  
  1442.                             if(!(*AbortTable[c])(c))
  1443.                             {
  1444.                                 InSequence = FALSE;
  1445.  
  1446.                                 break;
  1447.                             }
  1448.                         }
  1449.                     }
  1450.                 }
  1451.                 else
  1452.                 {
  1453.                     ConTempBuffer[Len] = c;
  1454.  
  1455.                     if(Len++ == 512)
  1456.                     {
  1457.                         (*ConDump)(ConTempBuffer,Len);
  1458.  
  1459.                         Len = 0;
  1460.                     }
  1461.                 }
  1462.             }
  1463.         }
  1464.     }
  1465.     else
  1466.     {
  1467.         while(Size-- > 0)
  1468.         {
  1469.             if(c = *String++)
  1470.             {
  1471.                 if(SpecialTable[c])
  1472.                 {
  1473.                     if(Len)
  1474.                     {
  1475.                         (*ConDump)(ConTempBuffer,Len);
  1476.  
  1477.                         Len = 0;
  1478.                     }
  1479.  
  1480.                     if(InSequence = (*SpecialTable[c])(c))
  1481.                     {
  1482.                         while(Size-- > 0)
  1483.                         {
  1484.                             c = *String++;
  1485.  
  1486.                             if(!(*AbortTable[c])(c))
  1487.                             {
  1488.                                 InSequence = FALSE;
  1489.  
  1490.                                 break;
  1491.                             }
  1492.                         }
  1493.                     }
  1494.                 }
  1495.                 else
  1496.                 {
  1497.                     ConTempBuffer[Len] = c;
  1498.  
  1499.                     if(Len++ == 512)
  1500.                     {
  1501.                         (*ConDump)(ConTempBuffer,Len);
  1502.  
  1503.                         Len = 0;
  1504.                     }
  1505.                 }
  1506.             }
  1507.         }
  1508.     }
  1509.  
  1510.     if(Len)
  1511.         (*ConDump)(ConTempBuffer,Len);
  1512. }
  1513.  
  1514.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1515.      *
  1516.      *    Process data, hex mode flavour, seven bits.
  1517.      */
  1518.  
  1519. VOID 
  1520. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1521. {
  1522.     UBYTE    DummyBuffer[40],c;
  1523.     LONG    Fit,Spaces,Current;
  1524.  
  1525.         /* How many characters will fit into the line? */
  1526.  
  1527.     Fit    = (LastColumn + 1) / 4;
  1528.  
  1529.         /* Which position are we currently in? */
  1530.  
  1531.     Current    = CursorX / 3;
  1532.  
  1533.         /* Weird cursor position? */
  1534.  
  1535.     if(Current >= Fit || (CursorX % 3))
  1536.     {
  1537.         ConProcessData7("\r\n",2);
  1538.  
  1539.         Current = 0;
  1540.     }
  1541.  
  1542.         /* Check the font type. */
  1543.  
  1544.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1545.     {
  1546.         while(Size-- > 0)
  1547.         {
  1548.             c = (*String++) & 0x7F;
  1549.  
  1550.             Spaces = (Fit - Current) * 3 + Current - 3;
  1551.  
  1552.             if(c > ' ' && c < 127)
  1553.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1554.             else
  1555.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1556.  
  1557.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1558.  
  1559.             if(Current++ == Fit - 1)
  1560.             {
  1561.                 Current = 0;
  1562.  
  1563.                 ConProcessData7("\r\n",2);
  1564.             }
  1565.         }
  1566.     }
  1567.     else
  1568.     {
  1569.         while(Size-- > 0)
  1570.         {
  1571.             c = (*String++) & 0x7F;
  1572.  
  1573.             Spaces = (Fit - Current) * 3 + Current - 3;
  1574.  
  1575.             if(c && c != ' ')
  1576.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1577.             else
  1578.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1579.  
  1580.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1581.  
  1582.             if(Current++ == Fit - 1)
  1583.             {
  1584.                 Current = 0;
  1585.  
  1586.                 ConProcessData7("\r\n",2);
  1587.             }
  1588.         }
  1589.     }
  1590. }
  1591.  
  1592.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1593.      *
  1594.      *    Process data, hex mode flavour, eight bits.
  1595.      */
  1596.  
  1597. VOID 
  1598. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1599. {
  1600.     UBYTE    DummyBuffer[40],c;
  1601.     LONG    Fit,Spaces,Current;
  1602.  
  1603.         /* How many characters will fit into the line? */
  1604.  
  1605.     Fit    = (LastColumn + 1) / 4;
  1606.  
  1607.         /* Which position are we currently in? */
  1608.  
  1609.     Current    = CursorX / 3;
  1610.  
  1611.         /* Weird cursor position? */
  1612.  
  1613.     if(Current >= Fit || (CursorX % 3))
  1614.     {
  1615.         ConProcessData8("\r\n",2);
  1616.  
  1617.         Current = 0;
  1618.     }
  1619.  
  1620.         /* Check the font type. */
  1621.  
  1622.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1623.     {
  1624.         while(Size-- > 0)
  1625.         {
  1626.             c = *String++;
  1627.  
  1628.             Spaces = (Fit - Current) * 3 + Current - 3;
  1629.  
  1630.             if((c > ' ' && c < 127) || c > 160)
  1631.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1632.             else
  1633.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1634.  
  1635.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1636.  
  1637.             if(Current++ == Fit - 1)
  1638.             {
  1639.                 Current = 0;
  1640.  
  1641.                 ConProcessData8("\r\n",2);
  1642.             }
  1643.         }
  1644.     }
  1645.     else
  1646.     {
  1647.         while(Size-- > 0)
  1648.         {
  1649.             c = *String++;
  1650.  
  1651.             Spaces = (Fit - Current) * 3 + Current - 3;
  1652.  
  1653.             if(c && c != ' ')
  1654.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1655.             else
  1656.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1657.  
  1658.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1659.  
  1660.             if(Current++ == Fit - 1)
  1661.             {
  1662.                 Current = 0;
  1663.  
  1664.                 ConProcessData8("\r\n",2);
  1665.             }
  1666.         }
  1667.     }
  1668. }
  1669.  
  1670.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1671.      *
  1672.      *    Process data read from the serial line,
  1673.      *    special XPR flavour.
  1674.      */
  1675.  
  1676. VOID 
  1677. ConTransferHost(STRPTR Buffer,LONG Len)
  1678. {
  1679.     Len = XProtocolHostMon(XprIO,Buffer,Len,Config -> SerialConfig -> SerialBufferSize);
  1680.  
  1681.     if(TransferWindow)
  1682.         TransferCleanup();
  1683.  
  1684.     if(Len)
  1685.         ConProcess(Buffer,Len);
  1686. }
  1687.  
  1688.     /* ConsoleCommand(STRPTR String):
  1689.      *
  1690.      *    Just like SerialCommand(), but addresses the local
  1691.      *    terminal side.
  1692.      */
  1693.  
  1694. VOID 
  1695. ConsoleCommand(STRPTR String)
  1696. {
  1697.     STATIC UBYTE __far LocalBuffer[256];
  1698.  
  1699.     LONG    Count = 0,i,Len = strlen(String);
  1700.  
  1701.     BYTE    GotControl    = FALSE,
  1702.         GotEscape    = FALSE;
  1703.  
  1704.         /* Scan the string. */
  1705.  
  1706.     for(i = 0 ; i < Len ; i++)
  1707.     {
  1708.             /* We are looking for plain characters
  1709.              * and the control ('\') and escape
  1710.              * ('^') characters.
  1711.              */
  1712.  
  1713.         if(!GotControl && !GotEscape)
  1714.         {
  1715.                 /* Got a control character,
  1716.                  * the next byte will probably be
  1717.                  * a command sequence.
  1718.                  */
  1719.  
  1720.             if(String[i] == '\\')
  1721.             {
  1722.                 GotControl = TRUE;
  1723.  
  1724.                 continue;
  1725.             }
  1726.  
  1727.                 /* Got an escape character,
  1728.                  * the next byte will be some
  1729.                  * kind of control character
  1730.                  * (such as XON, XOF, bell, etc.).
  1731.                  */
  1732.  
  1733.             if(String[i] == '^')
  1734.             {
  1735.                 GotEscape = TRUE;
  1736.  
  1737.                 continue;
  1738.             }
  1739.  
  1740.                 /* This tells us to wait another
  1741.                  * second before continuing with
  1742.                  * the scanning.
  1743.                  */
  1744.  
  1745.             if(String[i] == '~')
  1746.                 continue;
  1747.  
  1748.                 /* Stuff the character into the
  1749.                  * buffer.
  1750.                  */
  1751.  
  1752.             LocalBuffer[Count++] = String[i];
  1753.         }
  1754.         else
  1755.         {
  1756.                 /* Convert the character to a control
  1757.                  * style character (^C, etc.).
  1758.                  */
  1759.  
  1760.             if(GotEscape)
  1761.             {
  1762.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1763.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1764.                 else
  1765.                     LocalBuffer[Count++] = String[i];
  1766.  
  1767.                 GotEscape = FALSE;
  1768.             }
  1769.  
  1770.                 /* The next character represents a command. */
  1771.  
  1772.             if(GotControl)
  1773.             {
  1774.                 switch(ToUpper(String[i]))
  1775.                 {
  1776.                         /* Translate code. */
  1777.  
  1778.                     case '*':
  1779.  
  1780.                         i++;
  1781.  
  1782.                         while(i < Len && String[i] == ' ')
  1783.                             i++;
  1784.  
  1785.                         if(i < Len)
  1786.                         {
  1787.                             UBYTE DummyBuffer[5],j = 0,Char;
  1788.  
  1789.                             if(String[i] >= '0' && String[i] <= '9')
  1790.                             {
  1791.                                 while(j < 3 && i < Len)
  1792.                                 {
  1793.                                     Char = String[i++];
  1794.  
  1795.                                     if(Char >= '0' && Char <= '9')
  1796.                                         DummyBuffer[j++] = Char;
  1797.                                     else
  1798.                                     {
  1799.                                         i--;
  1800.  
  1801.                                         break;
  1802.                                     }
  1803.                                 }
  1804.                             }
  1805.                             else
  1806.                             {
  1807.                                 while(j < 4 && i < Len)
  1808.                                 {
  1809.                                     Char = ToLower(String[i++]);
  1810.  
  1811.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1812.                                         DummyBuffer[j++] = Char;
  1813.                                     else
  1814.                                     {
  1815.                                         i--;
  1816.  
  1817.                                         break;
  1818.                                     }
  1819.                                 }
  1820.                             }
  1821.  
  1822.                             DummyBuffer[j] = 0;
  1823.  
  1824.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1825.                         }
  1826.  
  1827.                         i--;
  1828.  
  1829.                         break;
  1830.  
  1831.                         /* Execute an AmigaDOS command. */
  1832.  
  1833.                     case 'D':
  1834.  
  1835.                         return;
  1836.  
  1837.                         /* Execute an ARexx command. */
  1838.  
  1839.                     case 'A':
  1840.  
  1841.                         return;
  1842.  
  1843.                         /* Add the control character ('\'). */
  1844.  
  1845.                     case '\\':
  1846.  
  1847.                         LocalBuffer[Count++] = '\\';
  1848.                         break;
  1849.  
  1850.                         /* This is a backspace. */
  1851.  
  1852.                     case 'B':
  1853.  
  1854.                         LocalBuffer[Count++] = '\b';
  1855.                         break;
  1856.  
  1857.                         /* This is a form feed. */
  1858.  
  1859.                     case 'F':
  1860.  
  1861.                         LocalBuffer[Count++] = '\f';
  1862.                         break;
  1863.  
  1864.                         /* This is a line feed. */
  1865.  
  1866.                     case 'N':
  1867.  
  1868.                         LocalBuffer[Count++] = '\n';
  1869.                         break;
  1870.  
  1871.                         /* Send the current password. */
  1872.  
  1873.                     case 'P':
  1874.  
  1875.                         break;
  1876.  
  1877.                         /* This is a carriage return. */
  1878.  
  1879.                     case 'R':
  1880.  
  1881.                         LocalBuffer[Count++] = '\r';
  1882.                         break;
  1883.  
  1884.                         /* This is a tab. */
  1885.  
  1886.                     case 'T':
  1887.  
  1888.                         LocalBuffer[Count++] = '\t';
  1889.                         break;
  1890.  
  1891.                         /* Send the current user name. */
  1892.  
  1893.                     case 'U':
  1894.  
  1895.                         break;
  1896.  
  1897.                         /* Send a break across the serial line. */
  1898.  
  1899.                     case 'X':
  1900.  
  1901.                         break;
  1902.  
  1903.                         /* Feed the contents of the
  1904.                          * clipboard into the input
  1905.                          * stream.
  1906.                          */
  1907.  
  1908.                     case 'I':
  1909.  
  1910.                         if(Count)
  1911.                             ConProcess(LocalBuffer,Count);
  1912.  
  1913.                         Count = LoadClip(LocalBuffer,256);
  1914.  
  1915.                         break;
  1916.  
  1917.                         /* Send a string to the clipboard. */
  1918.  
  1919.                     case 'G':
  1920.  
  1921.                         if(String[i + 1])
  1922.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1923.  
  1924.                         return;
  1925.  
  1926.                         /* Produce the escape character. */
  1927.  
  1928.                     case 'E':
  1929.  
  1930.                         LocalBuffer[Count++] = ESC;
  1931.                         break;
  1932.  
  1933.                         /* Call a menu item. */
  1934.  
  1935.                     case 'C':
  1936.  
  1937.                         break;
  1938.  
  1939.                         /* Stuff the character into the buffer. */
  1940.  
  1941.                     default:
  1942.  
  1943.                         LocalBuffer[Count++] = String[i];
  1944.                         break;
  1945.                 }
  1946.  
  1947.                 GotControl = FALSE;
  1948.             }
  1949.         }
  1950.  
  1951.             /* If the buffer is full, release it. */
  1952.  
  1953.         if(Count == 256)
  1954.         {
  1955.             ConProcess(LocalBuffer,Count);
  1956.  
  1957.             Count = 0;
  1958.         }
  1959.     }
  1960.  
  1961.     if(Count)
  1962.         ConProcess(LocalBuffer,Count);
  1963. }
  1964.  
  1965.     /* ConBypass(STRPTR String,LONG Size):
  1966.      *
  1967.      *    Bypass the `normal' ConOutput() data processing.
  1968.      */
  1969.  
  1970. VOID __regargs
  1971. ConBypass(STRPTR String,LONG Size)
  1972. {
  1973.     if(Size < 0)
  1974.         Size = strlen(String);
  1975.  
  1976.     if(Size > 0)
  1977.     {
  1978.         ObtainTerminal();
  1979.  
  1980.         if(Marking)
  1981.             DropMarker();
  1982.  
  1983.         ClearCursor();
  1984.  
  1985.         (*ConProcessData)(String,Size);
  1986.  
  1987.         DrawCursor();
  1988.  
  1989.         ReleaseTerminal();
  1990.     }
  1991. }
  1992.  
  1993.     /* ConProcess(STRPTR String,LONG Size):
  1994.      *
  1995.      *    Process the contents of a string to be sent to the
  1996.      *    console window.
  1997.      */
  1998.  
  1999. VOID 
  2000. ConProcess(register STRPTR String,register LONG Size)
  2001. {
  2002.         /* If the capture filter happens to be disabled, write the
  2003.          * raw data.
  2004.          */
  2005.  
  2006.     if(!Config -> CaptureConfig -> CaptureFilterMode)
  2007.         CaptureToFile(String,Size);
  2008.  
  2009.         /* Feed the flow filter. */
  2010.  
  2011.     if(UseFlow)
  2012.     {
  2013.         if(Config -> SerialConfig -> StripBit8)
  2014.             FlowFilter(String,Size,0x7F);
  2015.         else
  2016.             FlowFilter(String,Size,0xFF);
  2017.     }
  2018.  
  2019.         /* Remember the data. */
  2020.  
  2021.     if(RememberOutput)
  2022.         RememberOutputText(String,Size);
  2023.  
  2024.         /* Check the traps if necessary. */
  2025.  
  2026.     if(WatchTraps)
  2027.         TrapFilter(String,Size);
  2028.  
  2029.         /* In quiet mode no characters are echoed to the
  2030.          * console window, they are just passed through
  2031.          * the data flow filter. Usually, this mode is
  2032.          * enabled by the dial panel.
  2033.          */
  2034.  
  2035.     if(!Quiet)
  2036.         PostData(String,Size);
  2037. }
  2038.  
  2039.     /* ConWrites(STRPTR String,...):
  2040.      *
  2041.      *    Output a string to the console.
  2042.      */
  2043.  
  2044. VOID __stdargs
  2045. ConWrites(STRPTR String,...)
  2046. {
  2047.     va_list    VarArgs;
  2048.  
  2049.     if(Marking)
  2050.         DropMarker();
  2051.  
  2052.     va_start(VarArgs,String);
  2053.     VSPrintf(SharedBuffer,String,VarArgs);
  2054.     va_end(VarArgs);
  2055.  
  2056.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  2057. }
  2058.  
  2059.     /* FlowInit():
  2060.      *
  2061.      *    Set up the data flow parser. The parser scans the serial
  2062.      *    output data for more or less interesting modem output
  2063.      *    (carrier lost, connect, etc.).
  2064.      */
  2065.  
  2066. VOID __regargs
  2067. FlowInit(BYTE FullReset)
  2068. {
  2069.     WORD i;
  2070.  
  2071.         /* Set up `NO CARRIER' message. */
  2072.  
  2073.     if(Config -> ModemConfig -> NoCarrier[0])
  2074.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  2075.     else
  2076.         AttentionBuffers[SCAN_NOCARRIER][0] = 0;
  2077.  
  2078.         /* Set up ZRQINIT message. */
  2079.  
  2080.     strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
  2081.  
  2082.         /* Set up `CONNECT' message. */
  2083.  
  2084.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  2085.  
  2086.         /* Set up `VOICE' message. */
  2087.  
  2088.     if(Config -> ModemConfig -> Voice[0])
  2089.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  2090.     else
  2091.         AttentionBuffers[SCAN_VOICE][0] = 0;
  2092.  
  2093.         /* Set up `RING' message. */
  2094.  
  2095.     if(Config -> ModemConfig -> Ring[0])
  2096.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  2097.     else
  2098.         AttentionBuffers[SCAN_RING][0] = 0;
  2099.  
  2100.         /* Set up `BUSY' message. */
  2101.  
  2102.     if(Config -> ModemConfig -> Busy[0])
  2103.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  2104.     else
  2105.         AttentionBuffers[SCAN_BUSY][0] = 0;
  2106.  
  2107.         /* Set up `NO DIALTONE' message. */
  2108.  
  2109.     if(Config -> ModemConfig -> NoDialTone[0])
  2110.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  2111.     else
  2112.         AttentionBuffers[SCAN_NODIALTONE][0] = 0;
  2113.  
  2114.         /* Set up `OK' message. */
  2115.  
  2116.     if(Config -> ModemConfig -> Ok[0])
  2117.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  2118.     else
  2119.         AttentionBuffers[SCAN_OK][0] = 0;
  2120.  
  2121.         /* Set up `ERROR' message. */
  2122.  
  2123.     if(Config -> ModemConfig -> Error[0])
  2124.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  2125.     else
  2126.         AttentionBuffers[SCAN_ERROR][0] = 0;
  2127.  
  2128.         /* Reset match counter. */
  2129.  
  2130.     FlowCount = 0;
  2131.  
  2132.         /* Reset indices. */
  2133.  
  2134.     memset(AttentionCount,0,sizeof(AttentionCount));
  2135.  
  2136.         /* Determine lengths. */
  2137.  
  2138.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2139.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  2140.  
  2141.     if(FullReset)
  2142.     {
  2143.             /* No, we are not yet looking for a baud rate. */
  2144.  
  2145.         BaudPending = FALSE;
  2146.  
  2147.             /* Reset the flags. */
  2148.  
  2149.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  2150.     }
  2151.  
  2152.         /* Is it safe to disable the flow filter? */
  2153.  
  2154.     if(!FullCheck && Online && Config -> SerialConfig -> CheckCarrier && !Config -> MiscConfig -> AutoUpload)
  2155.         UseFlow = FALSE;
  2156.     else
  2157.         UseFlow = TRUE;
  2158.  
  2159.         /* Full data check is a lot slower than looking for
  2160.          * just a single sequence (such as the `CONNECT'
  2161.          * below). This mode is reserved for the dial panel.
  2162.          */
  2163.  
  2164.     if(FullCheck)
  2165.     {
  2166.         ScanStart    = 0;
  2167.         ScanEnd        = SCAN_COUNT - 1;
  2168.     }
  2169.     else
  2170.     {
  2171.         if(Online)
  2172.         {
  2173.             ScanStart = SCAN_NOCARRIER;
  2174.  
  2175.             if(UsesZModem)
  2176.                 ScanEnd = SCAN_ZMODEM;
  2177.             else
  2178.                 ScanEnd = SCAN_NOCARRIER;
  2179.         }
  2180.         else
  2181.         {
  2182.             if(UsesZModem)
  2183.                 ScanStart = SCAN_ZMODEM;
  2184.             else
  2185.                 ScanStart = SCAN_CONNECT;
  2186.  
  2187.             ScanEnd = SCAN_RING;
  2188.         }
  2189.     }
  2190. }
  2191.  
  2192.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  2193.      *
  2194.      *    Text output, if necessary switching from gfx font
  2195.      *    to current default font.
  2196.      */
  2197.  
  2198. VOID __regargs
  2199. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  2200. {
  2201.     BYTE TextMode;
  2202.     LONG SameMode;
  2203.  
  2204.         /* Determine current text rendering mode. */
  2205.  
  2206.     if(GfxTable[Buffer[0]] == MODE_GFX)
  2207.         TextMode = MODE_GFX;
  2208.     else
  2209.     {
  2210.         TextMode = MODE_STANDARD;
  2211.  
  2212.         SetFont(RPort,TextFont);
  2213.     }
  2214.  
  2215.         /* Reset number of characters in common mode. */
  2216.  
  2217.     SameMode = 0;
  2218.  
  2219.         /* Scan until all input is processed. */
  2220.  
  2221.     FOREVER
  2222.     {
  2223.             /* Scan for characters in the current mode. */
  2224.  
  2225.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  2226.             SameMode++;
  2227.  
  2228.             /* Output the text found. */
  2229.  
  2230.         Text(RPort,Buffer,SameMode);
  2231.  
  2232.             /* Decrement number of remaining bytes. */
  2233.  
  2234.         Length -= SameMode;
  2235.  
  2236.             /* Anything left? */
  2237.  
  2238.         if(Length)
  2239.         {
  2240.                 /* Skip to next character. */
  2241.  
  2242.             Buffer        += SameMode;
  2243.             SameMode     = 0;
  2244.  
  2245.                 /* Change text output mode. */
  2246.  
  2247.             if(TextMode == MODE_GFX)
  2248.             {
  2249.                 SetFont(RPort,TextFont);
  2250.  
  2251.                 TextMode = MODE_STANDARD;
  2252.             }
  2253.             else
  2254.             {
  2255.                 SetFont(RPort,GFX);
  2256.  
  2257.                 TextMode = MODE_GFX;
  2258.             }
  2259.         }
  2260.         else
  2261.             break;
  2262.     }
  2263.  
  2264.         /* Reset font type. */
  2265.  
  2266.     if(TextMode == MODE_STANDARD)
  2267.         SetFont(RPort,GFX);
  2268. }
  2269.  
  2270.     /* ConvertKey():
  2271.      *
  2272.      *    The actual key conversion routine.
  2273.      */
  2274.  
  2275. STATIC LONG __inline
  2276. ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
  2277. {
  2278.     LONG Actual;
  2279.  
  2280.         /* Fill in the defaults. */
  2281.  
  2282.     FakeInputEvent -> ie_Code        = Code;
  2283.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  2284.     FakeInputEvent -> ie_position . ie_addr    = (APTR)Prev;
  2285.  
  2286.         /* Clear the buffer (sortof). */
  2287.  
  2288.     Buffer[0] = 0;
  2289.  
  2290.         /* Convert the codes. */
  2291.  
  2292.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  2293.         return(Actual);
  2294.     else
  2295.         return(0);
  2296. }
  2297.  
  2298.     /* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
  2299.      *
  2300.      *    Much more simplified raw key conversion routine.
  2301.      */
  2302.  
  2303. UBYTE __regargs
  2304. ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
  2305. {
  2306.     if(Buffer)
  2307.         Buffer[0] = 0;
  2308.  
  2309.     if(Len)
  2310.         *Len = 0;
  2311.  
  2312.         /* Key was pressed, not released. */
  2313.  
  2314.     if(!(Code & IECODE_UP_PREFIX))
  2315.     {
  2316.             /* These are the sequences mapped to special
  2317.              * control keys (cursor keys, function keys,
  2318.              * the help key).
  2319.              */
  2320.  
  2321.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2322.         {
  2323.             (STRPTR)"A",    CUP,
  2324.             (STRPTR)"B",    CDN,
  2325.             (STRPTR)"C",    CFW,
  2326.             (STRPTR)"D",    CBK,
  2327.  
  2328.             (STRPTR)"?~",    HLP,
  2329.  
  2330.             (STRPTR)"0~",    FN1,
  2331.             (STRPTR)"1~",    FN2,
  2332.             (STRPTR)"2~",    FN3,
  2333.             (STRPTR)"3~",    FN4,
  2334.             (STRPTR)"4~",    FN5,
  2335.             (STRPTR)"5~",    FN6,
  2336.             (STRPTR)"6~",    FN7,
  2337.             (STRPTR)"7~",    FN8,
  2338.             (STRPTR)"8~",    FN9,
  2339.             (STRPTR)"9~",    F10
  2340.         };
  2341.  
  2342.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2343.  
  2344.         UBYTE    ConvertBuffer[257];
  2345.         LONG    Actual;
  2346.  
  2347.             /* If it's a function or cursor key, clear the qualifier. */
  2348.  
  2349.         if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
  2350.             Qualifier = NULL;
  2351.         else
  2352.         {
  2353.                 /* Does it have a numeric keypad qualifier set? */
  2354.  
  2355.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2356.             {
  2357.                     /* Look at the vanilla result. */
  2358.  
  2359.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
  2360.                 {
  2361.                     STRPTR String;
  2362.  
  2363.                         /* Take a look at the results. */
  2364.  
  2365.                     switch(ConvertBuffer[0])
  2366.                     {
  2367.                         case '(':
  2368.                         case '[':
  2369.  
  2370.                             String = "\033OP";
  2371.                             break;
  2372.  
  2373.                         case ')':
  2374.                         case ']':
  2375.  
  2376.                             String = "\033OQ";
  2377.                             break;
  2378.  
  2379.                         case '/':
  2380.  
  2381.                             String = "\033OR";
  2382.                             break;
  2383.  
  2384.                         case '*':
  2385.  
  2386.                             String = "\033OS";
  2387.                             break;
  2388.  
  2389.                         default:
  2390.  
  2391.                             String = NULL;
  2392.                             break;
  2393.                     }
  2394.  
  2395.                     if(!String)
  2396.                     {
  2397.                         switch(Code)
  2398.                         {
  2399.                             case 0x5A:
  2400.  
  2401.                                 String = "\033OP";
  2402.                                 break;
  2403.  
  2404.                             case 0x5B:
  2405.  
  2406.                                 String = "\033OQ";
  2407.                                 break;
  2408.  
  2409.                             case 0x5C:
  2410.  
  2411.                                 String = "\033OR";
  2412.                                 break;
  2413.  
  2414.                             case 0x5D:
  2415.  
  2416.                                 String = "\033OS";
  2417.                                 break;
  2418.                         }
  2419.                     }
  2420.  
  2421.                         /* Return the PFx key code. */
  2422.  
  2423.                     if(String)
  2424.                     {
  2425.                         if(Buffer)
  2426.                             memcpy(Buffer,String,3);
  2427.  
  2428.                         if(Len)
  2429.                             *Len = 3;
  2430.  
  2431.                         return('\033');
  2432.                     }
  2433.                 }
  2434.             }
  2435.  
  2436.                 /* Does it have a shift qualifier set? */
  2437.  
  2438.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2439.             {
  2440.                     /* Do the conversion... */
  2441.  
  2442.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
  2443.                 {
  2444.                         /* Did it produce a tab key? If so, transfer
  2445.                          * Esc tab instead.
  2446.                          */
  2447.  
  2448.                     if(ConvertBuffer[0] == '\t')
  2449.                     {
  2450.                         if(Len)
  2451.                             *Len = 2;
  2452.  
  2453.                         if(Buffer)
  2454.                             memcpy(Buffer,"\033\t",2);
  2455.  
  2456.                         return('\033');
  2457.                     }
  2458.                 }
  2459.             }
  2460.  
  2461.                 /* Does it have the control qualifier set? */
  2462.  
  2463.             if(Qualifier & IEQUALIFIER_CONTROL)
  2464.             {
  2465.                     /* Do the conversion... */
  2466.  
  2467.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
  2468.                 {
  2469.                         /* Did it produce a space or an `at' sign? */
  2470.  
  2471.                     if(ConvertBuffer[0] == ' ' || ConvertBuffer[0] == '@')
  2472.                     {
  2473.                             /* If so, produce a nul instead. */
  2474.  
  2475.                         if(Len)
  2476.                             *Len = 1;
  2477.  
  2478.                         if(Buffer)
  2479.                             Buffer[0] = 0;
  2480.  
  2481.                         return(0);
  2482.                     }
  2483.                 }
  2484.             }
  2485.         }
  2486.  
  2487.             /* Do the final conversion... */
  2488.  
  2489.         if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
  2490.         {
  2491.                 /* Are we to swap the backspace and
  2492.                  * delete keys?
  2493.                  */
  2494.  
  2495.             if(Config -> EmulationConfig -> SwapBSDelete)
  2496.             {
  2497.                 register WORD i;
  2498.  
  2499.                 for(i = 0 ; i < Actual ; i++)
  2500.                 {
  2501.                     if(ConvertBuffer[i] == BKS)
  2502.                         ConvertBuffer[i] = DEL;
  2503.                     else
  2504.                     {
  2505.                         if(ConvertBuffer[i] == DEL)
  2506.                             ConvertBuffer[i] = BKS;
  2507.                     }
  2508.                 }
  2509.             }
  2510.  
  2511.                 /* Translated sequence starts
  2512.                  * with a CSI, let's have a look
  2513.                  * at the associated control
  2514.                  * key.
  2515.                  */
  2516.  
  2517.             if(ConvertBuffer[0] == CSI)
  2518.             {
  2519.                 register WORD i;
  2520.  
  2521.                 for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2522.                 {
  2523.                         /* Does it match? */
  2524.  
  2525.                     if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2526.                     {
  2527.                             /* Store the length. */
  2528.  
  2529.                         if(Len)
  2530.                             *Len = 1;
  2531.  
  2532.                             /* Store the result. */
  2533.  
  2534.                         if(Buffer)
  2535.                         {
  2536.                             Buffer[0] = ConversionTable[i] . Result;
  2537.                             Buffer[1] = 0;
  2538.                         }
  2539.  
  2540.                         return(ConversionTable[i] . Result);
  2541.                     }
  2542.                 }
  2543.             }
  2544.  
  2545.                 /* Store the number of characters converted. */
  2546.  
  2547.             if(Len)
  2548.                 *Len = Actual;
  2549.  
  2550.                 /* Store the converted characters. */
  2551.  
  2552.             if(Buffer)
  2553.                 memcpy(Buffer,ConvertBuffer,Actual);
  2554.  
  2555.             return(ConvertBuffer[0]);
  2556.         }
  2557.     }
  2558.  
  2559.     return(0);
  2560. }
  2561.  
  2562.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2563.      *
  2564.      *    Convert a raw key information according to the
  2565.      *    current keymap settings.
  2566.      */
  2567.  
  2568. UBYTE __regargs
  2569. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2570. {
  2571.         /* Is this really a keyboard event? */
  2572.  
  2573.     if(Massage -> Class == IDCMP_RAWKEY)
  2574.         return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
  2575.     else
  2576.     {
  2577.         if(Buffer)
  2578.             Buffer[0] = 0;
  2579.  
  2580.         if(Len)
  2581.             *Len = 0;
  2582.  
  2583.         return(0);
  2584.     }
  2585. }
  2586.  
  2587.     /* DoBackspace():
  2588.      *
  2589.      *    Special function: perform backspace.
  2590.      */
  2591.  
  2592. BYTE 
  2593. DoBackspace()
  2594. {
  2595.     Capture("\b",1);
  2596.  
  2597.     if(CursorX)
  2598.     {
  2599.         WORD DeltaX,MinX;
  2600.  
  2601.         CursorX--;
  2602.  
  2603.             // What backspace mode are we in?
  2604.  
  2605.         switch(Config -> EmulationConfig -> DestructiveBackspace)
  2606.         {
  2607.                 // Do nothing
  2608.  
  2609.             case 0:
  2610.  
  2611.                 ClipBlitCursor(FALSE,TRUE);
  2612.                 break;
  2613.  
  2614.                 // Shift the line to the left
  2615.  
  2616.             case 2:
  2617.  
  2618.                 BackupRender();
  2619.  
  2620.                 RasterEraseCharacters(1);
  2621.  
  2622.                 if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
  2623.                 {
  2624.                     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2625.                     {
  2626.                         DeltaX    = TextFontWidth;
  2627.                         MinX    = MUL_X(CursorX);
  2628.                     }
  2629.                     else
  2630.                     {
  2631.                         DeltaX    = TextFontWidth / 2;
  2632.                         MinX    = MUL_X(CursorX) / 2;
  2633.                     }
  2634.                 }
  2635.                 else
  2636.                 {
  2637.                     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2638.                     {
  2639.                         DeltaX    = TextFontWidth / 2;
  2640.                         MinX    = MUL_X(CursorX) / 2;
  2641.                     }
  2642.                     else
  2643.                     {
  2644.                         DeltaX    = TextFontWidth;
  2645.                         MinX    = MUL_X(CursorX);
  2646.                     }
  2647.                 }
  2648.  
  2649.                 ScrollLineEraseCharacters(1);
  2650.  
  2651.                 ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2652.  
  2653.                 BackupRender();
  2654.  
  2655.                 ClipBlitCursor(FALSE,TRUE);
  2656.  
  2657.                 break;
  2658.  
  2659.                 // Clear the character below the cursor
  2660.  
  2661.             default:
  2662.  
  2663.                 ClipBlitCursor(FALSE,TRUE);
  2664.  
  2665.                 ObtainSemaphore(RasterSemaphore);
  2666.  
  2667.                 Raster[CursorY * RasterWidth + CursorX] = ' ';
  2668.  
  2669.                 ReleaseSemaphore(RasterSemaphore);
  2670.  
  2671.                 BackupRender();
  2672.  
  2673.                 if(FontScalingRequired)
  2674.                     PrintScaled(" ",1,CurrentFontScale);
  2675.                 else
  2676.                     Text(RPort," ",1);
  2677.  
  2678.                 BackupRender();
  2679.  
  2680.                 break;
  2681.         }
  2682.     }
  2683.  
  2684.     return(FALSE);
  2685. }
  2686.  
  2687.     /* DoBeep():
  2688.      *
  2689.      *    The real interface to the beep routine.
  2690.      */
  2691.  
  2692. BYTE 
  2693. DoBeep()
  2694. {
  2695.     BellSignal();
  2696.  
  2697.         /* Capture the bell. */
  2698.  
  2699.     if(Config -> CaptureConfig -> CaptureFilterMode == FILTER_NONE)
  2700.         Capture("\a",1);
  2701.  
  2702.     return(FALSE);
  2703. }
  2704.  
  2705.     /* DoxON():
  2706.      *
  2707.      *    Perform XON (stop data flow).
  2708.      */
  2709.  
  2710. BYTE 
  2711. DoxON()
  2712. {
  2713.     if(Config -> SerialConfig -> xONxOFF)
  2714.         Status = STATUS_HOLDING;
  2715.  
  2716.     return(FALSE);
  2717. }
  2718.  
  2719.     /* DoLF():
  2720.      *
  2721.      *    Special function: perform line feed.
  2722.      */
  2723.  
  2724. BYTE 
  2725. DoLF()
  2726. {
  2727.     if(Config -> TerminalConfig -> ReceiveLF == LF_ASLFCR)
  2728.     {
  2729.         CursorX = 0;
  2730.  
  2731.         DownLine();
  2732.  
  2733.         ClipBlitCursor(FALSE,TRUE);
  2734.  
  2735.         Capture("\n",1);
  2736.     }
  2737.     else
  2738.     {
  2739.         if(Config -> TerminalConfig -> ReceiveLF == LF_ASLF)
  2740.         {
  2741.             DownLine();
  2742.  
  2743.             ClipBlitCursor(FALSE,TRUE);
  2744.         }
  2745.     }
  2746.  
  2747.     return(FALSE);
  2748. }
  2749.  
  2750.     /* DoShiftIn():
  2751.      *
  2752.      *    Special function: Shift into graphics mode
  2753.      */
  2754.  
  2755. BYTE 
  2756. DoShiftIn()
  2757. {
  2758.     if(CharMode[1] == TABLE_GFX && GFX)
  2759.         CurrentFont = GFX;
  2760.  
  2761.     if(CharMode[1] == TABLE_ASCII)
  2762.         CurrentFont = TextFont;
  2763.  
  2764.     SetFont(RPort,CurrentFont);
  2765.  
  2766.     ConOutputUpdate();
  2767.  
  2768.     Charset = 1;
  2769.  
  2770.     return(FALSE);
  2771. }
  2772.  
  2773.     /* DoShiftOut():
  2774.      *
  2775.      *    Special function: Shift out of graphics mode
  2776.      */
  2777.  
  2778. BYTE 
  2779. DoShiftOut()
  2780. {
  2781.     if(CharMode[0] == TABLE_GFX && GFX)
  2782.         CurrentFont = GFX;
  2783.  
  2784.     if(CharMode[0] == TABLE_ASCII)
  2785.         CurrentFont = TextFont;
  2786.  
  2787.     SetFont(RPort,CurrentFont);
  2788.  
  2789.     ConOutputUpdate();
  2790.  
  2791.     Charset = 0;
  2792.  
  2793.     return(FALSE);
  2794. }
  2795.  
  2796.     /* DoCR_LF():
  2797.      *
  2798.      *    Special function: perform carriage return and line feed.
  2799.      */
  2800.  
  2801. BYTE 
  2802. DoCR_LF()
  2803. {
  2804.     CursorX = 0;
  2805.  
  2806.     DownLine();
  2807.  
  2808.     ClipBlitCursor(FALSE,TRUE);
  2809.  
  2810.     Capture("\n",1);
  2811.  
  2812.     return(FALSE);
  2813. }
  2814.  
  2815.     /* DoFF():
  2816.      *
  2817.      *    Special function: perform form feed.
  2818.      */
  2819.  
  2820. BYTE 
  2821. DoFF()
  2822. {
  2823.     if(Config -> EmulationConfig -> NewLineMode)
  2824.     {
  2825.         CursorX = 0;
  2826.  
  2827.         DoCR_LF();
  2828.     }
  2829.     else
  2830.     {
  2831.         EraseScreen("2");
  2832.  
  2833.         CursorX = CursorY = 0;
  2834.  
  2835.         ClipBlitCursor(FALSE,TRUE);
  2836.  
  2837.         ConFontScaleUpdate();
  2838.  
  2839.         Capture("\n",1);
  2840.     }
  2841.  
  2842.     return(FALSE);
  2843. }
  2844.  
  2845.     /* DoLF_FF_VT():
  2846.      *
  2847.      *    Special function: handle line feed, form feed and vertical
  2848.      *    tab.
  2849.      */
  2850.  
  2851. BYTE 
  2852. DoLF_FF_VT()
  2853. {
  2854.     if(Config -> EmulationConfig -> NewLineMode)
  2855.         DoCR_LF();
  2856.     else
  2857.         DoLF();
  2858.  
  2859.     return(FALSE);
  2860. }
  2861.  
  2862.     /* DoCR():
  2863.      *
  2864.      *    Special function: handle carriage return.
  2865.      */
  2866.  
  2867. BYTE 
  2868. DoCR()
  2869. {
  2870.     if(Config -> EmulationConfig -> NewLineMode || Config -> TerminalConfig -> ReceiveCR == CR_ASCRLF)
  2871.         DoCR_LF();
  2872.     else
  2873.     {
  2874.         if(Config -> TerminalConfig -> ReceiveCR == CR_ASCR)
  2875.         {
  2876.             CursorX = 0;
  2877.  
  2878.             ClipBlitCursor(FALSE,TRUE);
  2879.  
  2880.             Capture("\n",1);
  2881.         }
  2882.     }
  2883.  
  2884.     return(FALSE);
  2885. }
  2886.  
  2887.     /* DoTab():
  2888.      *
  2889.      *    Special function: handle tab, move cursor to next
  2890.      *    tab stop.
  2891.      */
  2892.  
  2893. BYTE 
  2894. DoTab()
  2895. {
  2896.     WORD Column;
  2897.  
  2898.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2899.         Column = LastColumn;
  2900.     else
  2901.         Column = ((LastColumn + 1) / 2) - 1;
  2902.  
  2903.     if(Config -> EmulationConfig -> LineWrap)
  2904.     {
  2905.         if(CursorX >= LastColumn)
  2906.         {
  2907.             CursorX = 0;
  2908.  
  2909.             DownLine();
  2910.         }
  2911.         else
  2912.         {
  2913.             while(CursorX < Column)
  2914.             {
  2915.                 CursorX++;
  2916.  
  2917.                 if(TabStops[CursorX])
  2918.                     break;
  2919.             }
  2920.         }
  2921.     }
  2922.     else
  2923.     {
  2924.         while(CursorX < Column)
  2925.         {
  2926.             CursorX++;
  2927.  
  2928.             if(TabStops[CursorX])
  2929.                 break;
  2930.         }
  2931.     }
  2932.  
  2933.     ClipBlitCursor(FALSE,TRUE);
  2934.  
  2935.     Capture("\t",1);
  2936.  
  2937.     return(FALSE);
  2938. }
  2939.  
  2940.     /* DoEnq():
  2941.      *
  2942.      *    Special function: send answerback message.
  2943.      */
  2944.  
  2945. BYTE 
  2946. DoEnq()
  2947. {
  2948.     if(Config -> EmulationConfig -> AnswerBack[0])
  2949.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  2950.  
  2951.     return(FALSE);
  2952. }
  2953.  
  2954.     /* DoEsc():
  2955.      *
  2956.      *    Start new control sequence.
  2957.      */
  2958.  
  2959. BYTE 
  2960. DoEsc()
  2961. {
  2962.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2963.         (* ConDump)("^",1);
  2964.  
  2965.     return(TRUE);
  2966. }
  2967.  
  2968.     /* DoCsi():
  2969.      *
  2970.      *    Start new control sequence.
  2971.      */
  2972.  
  2973. BYTE 
  2974. DoCsi()
  2975. {
  2976.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2977.         (* ConDump)("^[",2);
  2978.  
  2979.     ParseCode('[');
  2980.  
  2981.     return(TRUE);
  2982. }
  2983.  
  2984.     /* DoNewEsc(UBYTE Char):
  2985.      *
  2986.      *    Start new control sequence.
  2987.      */
  2988.  
  2989. BYTE 
  2990. DoNewEsc(UBYTE Char)
  2991. {
  2992.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2993.         (* ConDump)("^",1);
  2994.  
  2995.     DoCancel();
  2996.  
  2997.     return(TRUE);
  2998. }
  2999.  
  3000.     /* DoNewCsi(UBYTE Char):
  3001.      *
  3002.      *    Start new control sequence.
  3003.      */
  3004.  
  3005. BYTE 
  3006. DoNewCsi(UBYTE Char)
  3007. {
  3008.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3009.         (* ConDump)("^[",2);
  3010.  
  3011.     DoCancel();
  3012.  
  3013.     return(ParseCode('['));
  3014. }
  3015.